<script setup lang="ts">
import Sortable from 'sortablejs'
import { ElMessageBox } from 'element-plus'
import useUserStore from '@/store/modules/user'
import storage from '@/utils/storage'

defineOptions({
  name: 'StorageBox',
})

const props = withDefaults(
  defineProps<{
    name: string
    modelValue: object | any[]
    title?: string
  }>(),
  {
    title: '储存箱',
  },
)

const emits = defineEmits<{
  'update:modelValue': [
    value: object | any[],
  ]
  'takeOut': [
    value: object | any[],
  ]
}>()

const slots = useSlots()

const userStore = useUserStore()

const list = ref<{
  title: string
  content: string
}[]>([])

onMounted(() => {
  recoveryStorage()
})

function onAdd() {
  ElMessageBox.prompt('请输入一个方便记忆的名称', '', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    inputPattern: /\S/,
    inputErrorMessage: '名称不能为空',
  }).then(({ value }) => {
    if (value) {
      list.value.push({
        title: value,
        content: JSON.stringify(props.modelValue),
      })
      updateStorage()
    }
  })
}

function onGet(content: string) {
  emits('update:modelValue', JSON.parse(content))
  emits('takeOut', JSON.parse(content))
}

function onRemove(index: number) {
  list.value.splice(index, 1)
  updateStorage()
}

function sortStorage(newIndex: number, oldIndex: number) {
  list.value.splice(newIndex, 0, list.value.splice(oldIndex, 1)[0])
  updateStorage()
}

function updateStorage() {
  const storageBoxData = storage.session.has('storageBoxData') ? JSON.parse(storage.session.get('storageBoxData') as string) : {}
  storageBoxData[userStore.account] = storageBoxData[userStore.account] || {}
  storageBoxData[userStore.account][props.name] = list.value
  storage.session.set('storageBoxData', JSON.stringify(storageBoxData))
}

function recoveryStorage() {
  if (storage.session.has('storageBoxData')) {
    list.value = JSON.parse(storage.session.get('storageBoxData') as string)[userStore.account][props.name] || []
  }
}

const containerRef = ref()

// eslint-disable-next-line unused-imports/no-unused-vars
let sortable: Sortable
watch(() => containerRef.value, (val) => {
  if (val) {
    sortable = new Sortable(containerRef.value, {
      animation: 200,
      ghostClass: 'ghost',
      draggable: '.item',
      onUpdate: (e) => {
        if (e.newIndex !== undefined && e.oldIndex !== undefined) {
          sortStorage(e.newIndex, e.oldIndex)
        }
      },
    })
  }
})
</script>

<template>
  <el-dropdown placement="bottom" trigger="hover">
    <slot v-if="slots.default" />
    <svg-icon v-else name="ep:message-box" :size="16" />
    <template #dropdown>
      <div class="container">
        <div class="title-bar">
          <div class="title">
            {{ title }}
          </div>
          <div class="icons">
            <svg-icon name="ep:plus" @click="onAdd" />
          </div>
        </div>
        <el-scrollbar v-if="list.length > 0" max-height="200px">
          <div ref="containerRef" class="list">
            <div v-for="(item, index) in list" :key="`${index}_${item.title}`" :title="item.title" class="item" @click="onGet(item.content)">
              <el-text truncated class="name">
                {{ item.title }}
              </el-text>
              <svg-icon name="ep:delete" class="delete" @click.stop="onRemove(index)" />
            </div>
          </div>
        </el-scrollbar>
        <div v-else class="empty">
          <svg-icon name="tabler:mood-empty" :size="40" />
          <el-text>空空如也</el-text>
        </div>
      </div>
    </template>
  </el-dropdown>
</template>

<style lang="scss" scoped>
.container {
  width: 200px;

  .title-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 40px;
    padding: 0 12px;
    margin-bottom: -6px;

    .title {
      font-size: 14px;
      font-weight: bold;
    }

    .icons {
      display: flex;
      align-items: center;

      .icon {
        font-size: 20px;
        cursor: pointer;
      }
    }
  }

  :deep(.el-scrollbar__wrap) {
    width: 100%;
    overscroll-behavior: contain;
  }

  .list {
    display: flex;
    flex-direction: column;
    padding: 0 12px;
    margin-bottom: 6px;

    .item {
      position: relative;
      height: 36px;
      padding: 0 8px;
      margin: 5px 0;
      display: flex;
      align-items: center;
      border: 1px solid var(--el-border-color);
      border-radius: 4px;
      background-color: var(--el-bg-color);
      cursor: pointer;
      transition: var(--el-transition-color), var(--el-transition-border);

      &:hover {
        border: 1px solid var(--el-color-primary);
      }

      &.ghost {
        opacity: 0;
      }

      * {
        user-select: none;
      }

      .name {
        flex: 1;
        margin: 0 16px 0 8px;
        color: var(--el-text-color-primary);
        mask-image: linear-gradient(to right, #000 calc(100% - 20px), transparent);
      }

      .delete {
        position: absolute;
        right: 5px;
        width: 1.5em;
        height: 1.5em;
        border-radius: 50%;
        font-size: 14px;
        color: var(--el-text-color-disabled);
        transition: var(--el-transition-color), background-color 0.3s;

        &:hover {
          color: var(--el-text-color-primary);
          background-color: var(--el-fill-color);
        }
      }
    }
  }

  .empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 20px 0;
    color: var(--el-text-color-placeholder);

    .el-text {
      margin-top: 10px;
      display: flex;
      align-items: center;
      color: var(--el-text-color-placeholder);
    }
  }
}
</style>
